package com.sencorsta.ids.core.data.redis;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Tuple;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.Map;
import java.util.Set;

public class RedisDataUtil {
	// 备份数据
	private static void backups(String path, Object o) throws IOException {
		File file = new File(path);
		if (!file.exists()) {
			file.getParentFile().mkdirs();
			file.createNewFile();
		}
		FileOutputStream outStream = new FileOutputStream(file);
		outStream.write(o.toString().getBytes());
		outStream.close();
	}

	/**
	 * 拷贝数据
	 * 
	 * @param redisKeySrc
	 *            源Redis库
	 * @param redisKeyDes
	 *            目的Redis库
	 * @param dbIndexSrc
	 *            源DB序号
	 * @param dbIndexDes
	 *            目的DB序号
	 */
	public static void dataCopyAll(String redisKeySrc, String redisKeyDes, int dbIndexSrc, int dbIndexDes) {
		System.out.println("开始拷贝:");
		Jedis A = null;
		Jedis B = null;
		try {
			A = RedisProvider.getJedis(redisKeySrc);
			B = RedisProvider.getJedis(redisKeyDes);
			A.select(dbIndexSrc);
			B.select(dbIndexDes);

			Set<String> keys = A.keys("*");
			long time = new Date().getTime();
			String pathA = "backup/A/db" + dbIndexSrc + "/" + time + "/";
			String pathB = "backup/B/db" + dbIndexDes + "/" + time + "/";
			int count = 0;
			int goodCount = 0;
			for (String key : keys) {
				count++;
				System.out.println("正在拷贝:" + key + "(" + count + "/" + keys.size() + ")");
				String type = A.type(key);
				if (type.equals("string")) {
					String value = A.get(key);
					backups(pathA + key + ".json", value); // 主表数据备份

					String copy = B.get(key);
					if (copy != null) {
						backups(pathB + key + ".json", value); // 主表数据备份
					}
					B.set(key, value);
					goodCount++;
				} else if (type.equals("hash")) {
					Map<String, String> value = A.hgetAll(key);
					backups(pathA + key + ".json", value); // 主表数据备份
					Map<String, String> copy = B.hgetAll(key);
					if (copy != null) {
						backups(pathB + key + ".json", value); // 主表数据备份
					}
					for (Map.Entry<String, String> entry : value.entrySet()) { // 直接把主表的数据覆盖到从表
						B.hset(key, entry.getKey(), entry.getValue());
					}
					goodCount++;
				} else if (type.equals("zset")) {
					Set<Tuple> value = A.zrangeWithScores(key, 0, -1);
					backups(pathA + key + ".json", value); // 主表数据备份
					Set<Tuple> copy = B.zrangeWithScores(key, 0, -1);
					if (copy != null) {
						backups(pathB + key + ".json", value); // 主表数据备份
					}
					for (Tuple entry : value) { // 直接把主表的数据覆盖到从表
						B.zadd(key, entry.getScore(), entry.getElement());
					}
					goodCount++;
				} else {
					System.out.println("拷贝失败!未知类型:" + type);
				}

			}
			System.out.println("拷贝完成!成功数:" + goodCount + "/" + count);
		} catch (Exception e) {
			System.err.println("拷贝出错:" + e.getMessage());
			for (StackTraceElement s : e.getStackTrace()) {
				System.err.println(s.toString());
			}
		} finally {
			RedisProvider.Close(A);
			RedisProvider.Close(B);
		}
	}

	public static void dataCopyByKey(String redisKeySrc, String redisKeyDes, int dbIndexSrc, int dbIndexDes,
			String key) {
		Jedis A = null;
		Jedis B = null;
		try {
			A = RedisProvider.getJedis(redisKeySrc);
			B = RedisProvider.getJedis(redisKeyDes);
			A.select(dbIndexSrc);
			B.select(dbIndexDes);
			long time = new Date().getTime();
			String pathA = "backup/A/db" + dbIndexSrc + "/" + time + "/";
			String pathB = "backup/B/db" + dbIndexDes + "/" + time + "/";
			String type = A.type(key);
			if (type.equals("string")) {
				String value = A.get(key);
				backups(pathA + key + ".json", value); // 主表数据备份

				String copy = B.get(key);
				if (copy != null) {
					backups(pathB + key + ".json", value); // 主表数据备份
				}
				B.set(key, value);
			} else if (type.equals("hash")) {
				Map<String, String> value = A.hgetAll(key);
				backups(pathA + key + ".json", value); // 主表数据备份
				Map<String, String> copy = B.hgetAll(key);
				if (copy != null) {
					backups(pathB + key + ".json", value); // 主表数据备份
				}
				for (Map.Entry<String, String> entry : value.entrySet()) { // 直接把主表的数据覆盖到从表
					B.hset(key, entry.getKey(), entry.getValue());
				}
			} else if (type.equals("zset")) {
				Set<Tuple> value = A.zrangeWithScores(key, 0, -1);
				backups(pathA + key + ".json", value); // 主表数据备份
				Set<Tuple> copy = B.zrangeWithScores(key, 0, -1);
				if (copy != null) {
					backups(pathB + key + ".json", value); // 主表数据备份
				}
				for (Tuple entry : value) { // 直接把主表的数据覆盖到从表
					B.zadd(key, entry.getScore(), entry.getElement());
				}
			} else {
				System.out.println("拷贝失败!未知类型:" + type);
			}
			System.out.println("拷贝完成!");
		} catch (Exception e) {
			System.err.println("拷贝出错:" + e.getMessage());
			for (StackTraceElement s : e.getStackTrace()) {
				System.err.println(s.toString());
			}
		} finally {
			RedisProvider.Close(A);
			RedisProvider.Close(B);
		}
	}

}
